package com.fastwire.carriere.controller;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

import com.fastwire.carriere.common.Messages;
import com.fastwire.carriere.common.constant.UserConstants;
import com.fastwire.carriere.common.exception.ResourceException;
import com.fastwire.carriere.common.util.CommonLogger;
import com.fastwire.carriere.common.util.DateUtil;
import com.fastwire.carriere.dao.DAOException;
import com.fastwire.carriere.dao.DAOFactory;
import com.fastwire.carriere.user.entity.UserSession;
import com.fastwire.carriere.user.vo.SessionVo;

public class ControllerProxy implements InvocationHandler {

	private final boolean isSessionReliable;
	private final SessionVo sessionVo;
	private Object delegate;

	public ControllerProxy(SessionVo sessionVo, boolean isSessionReliable) {
		super();
		this.sessionVo = sessionVo;
		this.isSessionReliable = isSessionReliable;

	}

	public Object bind(Object delegate) {
		this.delegate = delegate;
		return Proxy.newProxyInstance(
				this.delegate.getClass().getClassLoader(), this.delegate
						.getClass().getInterfaces(), this);
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		Object result = null;
		String methodName = method.getName();

		checkSessionVo();

		CommonLogger.info(this, "start " + methodName + " ...");

		result = method.invoke(delegate, args);

		CommonLogger.info(this, "finish " + methodName + " ...");

		return result;
	}

	public void checkSessionVo() throws DAOException, ResourceException {

		if (isSessionReliable && sessionVo != null) {
			UserSession userSession = DAOFactory
					.getInstance()
					.getUserSessionDao()
					.getUserSession(sessionVo.getUserName(),
							Long.parseLong(sessionVo.getSessionId()));

			if (userSession == null
					|| !UserConstants.STATUS_ACTIVE.equals(userSession
							.getStatus()))

			{

				throw new RuntimeException(
						Messages.getString("message.usersession.inactive.exception"));

			}

			java.util.Date loginDate = userSession.getLoginDate();

			long timeDiff = DateUtil.getDiffInSecs(loginDate);

			if (timeDiff < -12 * 3600) {
				throw new RuntimeException(
						Messages.getString("message.usersession.timeout.exception"));

			}

		}

	}

	public static String getRootException(Exception e) {
		Exception eCurrentException = e;
		Exception eRootException = null;

		while (eCurrentException != null) {
			Exception eNextLevelUp = (Exception) eCurrentException.getCause();

			if (eNextLevelUp == null || eNextLevelUp.getCause() == null) {
				eRootException = eCurrentException;
				break;
			} else {
				eCurrentException = eNextLevelUp;
			}
		}

		if (eRootException == null) {
			eRootException = e;
		}

		String errorMsg = null;
		if (eRootException instanceof UndeclaredThrowableException) {
			errorMsg = ((UndeclaredThrowableException) eRootException)
					.getUndeclaredThrowable().getMessage();
		} else if (eRootException instanceof RuntimeException) {
			errorMsg = eRootException.getMessage();
		} else
			errorMsg = eRootException.getCause().getMessage();

		CommonLogger.error(ControllerProxy.class, "errorMsg: ------------ "
				+ errorMsg);
		return errorMsg;
	}
}
